package iosr11.Service;

import iosr11.contact.dao.ContactsHelper;
import iosr11.data.Event;
import iosr11.data.ProjectGroup;
import iosr11.data.ProjectSubject;
import iosr11.data.Student;
import iosr11.data.User;
import iosr11.gbase.dao.AttendenceDAO;
import iosr11.gbase.dao.MarkDAO;
import iosr11.gbase.dao.ProjectGroupDAO;
import iosr11.gbase.dao.ProjectSubjectDAO;
import iosr11.gbase.dao.StudentDAO;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class ProjectGroupServiceImpl implements ProjectGroupService {

	private ProjectGroupDAO projectGroupDAO;
	private ProjectSubjectDAO projectSubjectDAO;
	private StudentDAO studentDAO;
	private ContactsHelper contactsDAO;
	private MarkDAO markDAO;
	private AttendenceDAO attendenceDAO;
	private Logger log = Logger.getLogger("service-log");

	
	@Override
	public List<ProjectGroup> getEventGroup(Event event) {
		// TODO Auto-generated method stub
		if (event==null){
			log.warning("nie podano eventu");
			return null;
		}
		if (event.getSeries()==null){
			log.warning("nie przypisano event serii - blad");
			return null;
		}
		StudentService studS = (StudentService) ServiceLocatorImpl.getInstance().getService(Student.class);
		List<Student> studenci = studS.getStudentsForEvent(event);
		if (studenci==null){
			log.warning("brak studentow do eventu - brak grup");
			return null;
		}
		System.out.println("studentow do eventu: "+studenci.size());
		List <String> grpurl = new ArrayList<String>();
		for (Student stud : studenci){
			if (stud.getProjectGrp()!=null){
				if (stud.getProjectGrp().getId()!=null){
					if (!grpurl.contains(stud.getProjectGrp().getId())){
						grpurl.add(stud.getProjectGrp().getId());
					}
				}
			}
		}
		System.out.println("liczba grup: "+grpurl.size());
		
		List <ProjectGroup> result= new ArrayList<ProjectGroup>();
		
		for (String url : grpurl){
			ProjectGroup tmp = this.getProjectGroupById(url);
			if (tmp!=null){
				if (tmp.getSubject()!=null){
					ProjectSubject tmpsub = projectSubjectDAO.getByID(tmp.getSubject().getId());
					tmp.setSubject(tmpsub);
				}
				result.add(tmp);
			}
		}
		System.out.println("liczba grup po wczytaniu: "+result.size());
		/* do zmiany na mape */
		for (Student stud : studenci){
			if (stud.getProjectGrp()!=null){
				if (stud.getProjectGrp().getId()!=null){
					for (ProjectGroup grupa : result){
						if (grupa.getId().equals(stud.getProjectGrp().getId())){
							grupa.addStudent(stud);
							stud.setProjectGrp(grupa);
							break;
						}
					}
				}
			}
		}
		
		return result;
	}
	
	
	@Override
	public Class<ProjectGroup> getServiceEntityClass() {
		return ProjectGroup.class;
	}

	@Override
	public boolean addStudentsToGroup(List<Student> students, ProjectGroup group) {
		// TODO Auto-generated method stub
		log.info("dodawanie grupy projektowej do listy studentow");
		for (Student student : students){
			if (!this.addStudentToGroup(student, group)){
				log.warning("wystapil blad przy dodawaniu student: "+student.getName());
				return false;
			}
		}
		return true;
	}

	@Override
	public boolean addStudentToGroup(Student student, ProjectGroup group) {
		log.info("dodawanie grupy projektowej do studenta");
		student.setProjectGrp(group);
		return studentDAO.update(student);
	}

	@Override
	public boolean removeStudentFromGroup(Student student) {
		student.setProjectGrp(null);
		return studentDAO.update(student);
	}

	@Override
	public boolean createProjectGroup(String groupName,
			ProjectSubject subject, List<Student> students) {
		ProjectGroup tmp = new ProjectGroup();
		tmp.setGroupName(groupName);
		tmp.setStudents(students);
		tmp.setSubject(subject);
		return this.addProjectGroup(tmp);
	}

	@Override
	public boolean addProjectGroup(ProjectGroup group) {
		log.info("dodawanie grupy");
		return projectGroupDAO.add(group);
	}	

	@Override
	public boolean removeSubject(ProjectGroup group, ProjectSubject subject) {
		if (group==null){
			log.warning("brak grupy - null");
			return false;
		}
		if (subject==null){
			log.warning("brak teamatu - null");
			return false;
		}
		if (group.getSubject()==null){
			log.info("grupa nie ma ustawionego tematu");
		}
		
		group.setSubject(null);
		subject.setGroup(null);
		if (!projectSubjectDAO.update(subject)){
			log.warning("nie nadpisano tematu");
			return false;
		}
		return projectGroupDAO.update(group);
	}

	@Override
	public boolean hasSubject(ProjectGroup group) {
		if (group == null) {
			log.info("nie podano grupy");
			return false;
		}
		ProjectGroup grp = this.getProjectGroupById(group.getId());
		if (grp == null) {
			log.info("brak grupy w bazie");
			return false;
		}
		if (grp.getSubject()==null)
			return false;
		else
			return true;
	}


	@Override
	public boolean setSubject(ProjectGroup group, ProjectSubject subject) {
		if (group==null){
			log.warning("brak grupy - null");
			return false;
		}
		if (subject==null){
			log.warning("brak teamatu - null");
			return false;
		}
		if (group.getSubject()==null){
			log.info("grupa nie ma ustawionego tematu");
		}
		
		group.setSubject(subject);
		subject.setGroup(group);
		if (!projectSubjectDAO.update(subject)){
			log.warning("nie nadpisano tematu");
			return false;
		}
		return projectGroupDAO.update(group);
	}
	
	private List<Student> getStudentsForProjectGroup(ProjectGroup group){
		// TODO
		List<Student> result = new ArrayList<Student>();
		List<Student> tmp = studentDAO.getAll();
		if (tmp==null){
			log.info("brak studentow w bazie");
			return null;
		}
		
		for (Student stud : tmp){
			if (stud.getProjectGrp()!=null){
				if (stud.getProjectGrp().getId()!=null){
					if (stud.getProjectGrp().getId().equals(group.getId())){
						log.info("znaleziono studenta dla grupy");
						result.add(stud);
					}
				}
			}
		}
		
		log.info("znaleziono "+result.size()+" studentow przypisanych do grupy");
		return result;
	}

	@Override
	public boolean deleteProjectGroup(ProjectGroup group) {
		// TODO Auto-generated method stub
		if (group.getSubject()!=null){
			log.info("jest referencja na temat - usuwanie info z tematu");
			ProjectSubject tmp = projectSubjectDAO.getByID(group.getSubject().getId());
			tmp.setGroup(null);
			if (!projectSubjectDAO.update(tmp)){
				log.info("aktualizacja tematu sie nie powiodla - przerwanie");
				return false;
			}
		}
		
		// usuwanie ref na grupe z studentow
		List<Student> students =this.getStudentsForProjectGroup(group);
		for (Student stud : students){
			stud.setProjectGrp(null);
			if (!studentDAO.update(stud)){
				log.info("aktualizacja studenta nie powiodla sie");
				return false;
			}
		}
		
		log.info("usuwanie grupy projektowej");
		return projectGroupDAO.delete(group);
	}

	@Override
	public List<ProjectGroup> getAll() {
		List<ProjectGroup> lista = projectGroupDAO.getAll();
		List<ProjectGroup> result = new ArrayList<ProjectGroup>();
		if (lista == null) return result;
		for (ProjectGroup group : lista){
			if (group!=null)
				result.add(this.getProjectGroupById(group.getId()));
		}
		return result;
	}

	private List<Student> getStudentsFullForProjectGroup(ProjectGroup group){
		log.info("pobieranie pelnych danych o studentach grupy projektowej");
		List<Student> result = new ArrayList<Student>();
		List<Student> lista = this.getStudentsForProjectGroup(group);
		if (lista==null){
			log.info("otrzymano pusta liste");
			return null;
		}
		log.info("otrzymano liste z "+lista.size()+" rekordami");
		for (Student stud : lista){
			if (stud.getUser()==null){
				log.warning("brak kontaktu dla studenta - null");
			}
			else if (stud.getUser().getId()==null){
				log.warning("brak kontaktu dla studenta - brak id usera - null");
			}
			else {
			User user = contactsDAO.getUserByRef(stud.getUser().getId());
			if (user == null){
				log.info("niepoprawny kontakt");
			}
			else {
				stud.setUser(user);
				stud.setProjectGrp(group);
				stud.setGrades(markDAO.getStudentMarks(stud));
				stud.setAttendences(attendenceDAO.getStudentsAttendence(stud));
				result.add(stud);
			}
			}
		}
		
		return result;
	}
	
	@Override
	public ProjectGroup getProjectGroup(String name) {
		// TODO Auto-generated method stub
		ProjectGroup group = projectGroupDAO.getByName(name);
		if (group==null){
			log.info("brak rekordu");
			return null;
		}
		log.info("znaleziono grupe pobieranie studentow");
		List<Student> lista = this.getStudentsFullForProjectGroup(group);
		group.setStudents(lista);
		// pobieranie tematu
		if (group.getSubject()!=null)
			if (group.getSubject()!=null){
				ProjectSubject subject = projectSubjectDAO.getByID(group.getSubject().getId());
				log.info("dodaje temat");
				group.setSubject(subject);
				subject.setGroup(group);
			}
		return group;
	}

	@Override
	public ProjectGroup getProjectGroupById(String id) {
		// TODO Auto-generated method stub
		ProjectGroup group = projectGroupDAO.getByID(id);
		if (group.getSubject()!=null)
			if (group.getSubject()!=null){
				ProjectSubject subject = projectSubjectDAO.getByID(group.getSubject().getId());
				log.info("dodaje temat");
				group.setSubject(subject);
				subject.setGroup(group);
			}
		List<Student> lista = this.getStudentsFullForProjectGroup(group);
		group.setStudents(lista);
		return group;
	}
	

	
	/* ============================================
	 * Settery dla springa
	 * ============================================
	 */
	
	
	public void setProjectGroupDAO(ProjectGroupDAO projectGroupDAO) {
		this.projectGroupDAO = projectGroupDAO;
	}

	public void setProjectSubjectDAO(ProjectSubjectDAO projectSubjectDAO) {
		this.projectSubjectDAO = projectSubjectDAO;
	}

	public void setStudentDAO(StudentDAO studentDAO) {
		this.studentDAO = studentDAO;
	}

	public void setMarkDAO(MarkDAO markDAO) {
		this.markDAO = markDAO;
	}

	public void setAttendenceDAO(AttendenceDAO attendenceDAO) {
		this.attendenceDAO = attendenceDAO;
	}

	public void setContactsDAO(ContactsHelper contactsDAO) {
		this.contactsDAO = contactsDAO;
	}

}
